/*
 * Copyright 2010 Srikanth Reddy Lingala
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.lingala.zip4j.model;

import java.util.ArrayList;

import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.progress.ProgressMonitor;
import net.lingala.zip4j.unzip.Unzip;
import net.lingala.zip4j.util.Zip4jUtil;

public class FileHeader {

    private int signature;

    private int versionMadeBy;

    private int versionNeededToExtract;

    private byte[] generalPurposeFlag;

    private int compressionMethod;

    private int lastModFileTime;

    private long crc32;

    private byte[] crcBuff;

    private long compressedSize;

    private long uncompressedSize;

    private int fileNameLength;

    private int extraFieldLength;

    private int fileCommentLength;

    private int diskNumberStart;

    private byte[] internalFileAttr;

    private byte[] externalFileAttr;

    private long offsetLocalHeader;

    private String fileName;

    private String fileComment;

    private boolean isDirectory;

    private boolean isEncrypted;

    private int encryptionMethod;

    private char[] password;

    private boolean dataDescriptorExists;

    private Zip64ExtendedInfo zip64ExtendedInfo;

    private AESExtraDataRecord aesExtraDataRecord;

    private ArrayList extraDataRecords;

    private boolean fileNameUTF8Encoded;

    public FileHeader() {
        encryptionMethod = -1;
        crc32 = 0;
        uncompressedSize = 0;
    }

    public int getSignature() {
        return signature;
    }

    public void setSignature(int signature) {
        this.signature = signature;
    }

    public int getVersionMadeBy() {
        return versionMadeBy;
    }

    public void setVersionMadeBy(int versionMadeBy) {
        this.versionMadeBy = versionMadeBy;
    }

    public int getVersionNeededToExtract() {
        return versionNeededToExtract;
    }

    public void setVersionNeededToExtract(int versionNeededToExtract) {
        this.versionNeededToExtract = versionNeededToExtract;
    }

    public byte[] getGeneralPurposeFlag() {
        return generalPurposeFlag;
    }

    public void setGeneralPurposeFlag(byte[] generalPurposeFlag) {
        this.generalPurposeFlag = generalPurposeFlag;
    }

    public int getCompressionMethod() {
        return compressionMethod;
    }

    public void setCompressionMethod(int compressionMethod) {
        this.compressionMethod = compressionMethod;
    }

    public int getLastModFileTime() {
        return lastModFileTime;
    }

    public void setLastModFileTime(int lastModFileTime) {
        this.lastModFileTime = lastModFileTime;
    }

    public long getCrc32() {
        return crc32 & 0xffffffffL;
    }

    public void setCrc32(long crc32) {
        this.crc32 = crc32;
    }

    public long getCompressedSize() {
        return compressedSize;
    }

    public void setCompressedSize(long compressedSize) {
        this.compressedSize = compressedSize;
    }

    public long getUncompressedSize() {
        return uncompressedSize;
    }

    public void setUncompressedSize(long uncompressedSize) {
        this.uncompressedSize = uncompressedSize;
    }

    public int getFileNameLength() {
        return fileNameLength;
    }

    public void setFileNameLength(int fileNameLength) {
        this.fileNameLength = fileNameLength;
    }

    public int getExtraFieldLength() {
        return extraFieldLength;
    }

    public void setExtraFieldLength(int extraFieldLength) {
        this.extraFieldLength = extraFieldLength;
    }

    public int getFileCommentLength() {
        return fileCommentLength;
    }

    public void setFileCommentLength(int fileCommentLength) {
        this.fileCommentLength = fileCommentLength;
    }

    public int getDiskNumberStart() {
        return diskNumberStart;
    }

    public void setDiskNumberStart(int diskNumberStart) {
        this.diskNumberStart = diskNumberStart;
    }

    public byte[] getInternalFileAttr() {
        return internalFileAttr;
    }

    public void setInternalFileAttr(byte[] internalFileAttr) {
        this.internalFileAttr = internalFileAttr;
    }

    public byte[] getExternalFileAttr() {
        return externalFileAttr;
    }

    public void setExternalFileAttr(byte[] externalFileAttr) {
        this.externalFileAttr = externalFileAttr;
    }

    public long getOffsetLocalHeader() {
        return offsetLocalHeader;
    }

    public void setOffsetLocalHeader(long offsetLocalHeader) {
        this.offsetLocalHeader = offsetLocalHeader;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileComment() {
        return fileComment;
    }

    public void setFileComment(String fileComment) {
        this.fileComment = fileComment;
    }

    public boolean isDirectory() {
        return isDirectory;
    }

    public void setDirectory(boolean isDirectory) {
        this.isDirectory = isDirectory;
    }

    /**
     * Extracts file to the specified directory
     *
     * @param zipModel
     * @param outPath
     * @throws ZipException
     */
    public void extractFile(ZipModel zipModel, String outPath,
                            ProgressMonitor progressMonitor, boolean runInThread) throws ZipException {
        extractFile(zipModel, outPath, null, progressMonitor, runInThread);
    }

    /**
     * Extracts file to the specified directory using any
     * user defined parameters in UnzipParameters
     *
     * @param zipModel
     * @param outPath
     * @param unzipParameters
     * @throws ZipException
     */
    public void extractFile(ZipModel zipModel, String outPath,
                            UnzipParameters unzipParameters, ProgressMonitor progressMonitor, boolean runInThread) throws ZipException {
        extractFile(zipModel, outPath, unzipParameters, null, progressMonitor, runInThread);
    }

    /**
     * Extracts file to the specified directory using any
     * user defined parameters in UnzipParameters. Output file name
     * will be overwritten with the value in newFileName. If this
     * parameter is null, then file name will be the same as in
     * FileHeader.getFileName
     *
     * @param zipModel
     * @param outPath
     * @param unzipParameters
     * @throws ZipException
     */
    public void extractFile(ZipModel zipModel, String outPath,
                            UnzipParameters unzipParameters, String newFileName,
                            ProgressMonitor progressMonitor, boolean runInThread) throws ZipException {
        if (zipModel == null) {
            throw new ZipException("input zipModel is null");
        }

        if (!Zip4jUtil.checkOutputFolder(outPath)) {
            throw new ZipException("Invalid output path");
        }

        if (this == null) {
            throw new ZipException("invalid file header");
        }
        Unzip unzip = new Unzip(zipModel);
        unzip.extractFile(this, outPath, unzipParameters, newFileName, progressMonitor, runInThread);
    }

    public boolean isEncrypted() {
        return isEncrypted;
    }

    public void setEncrypted(boolean isEncrypted) {
        this.isEncrypted = isEncrypted;
    }

    public int getEncryptionMethod() {
        return encryptionMethod;
    }

    public void setEncryptionMethod(int encryptionMethod) {
        this.encryptionMethod = encryptionMethod;
    }

    public char[] getPassword() {
        return password;
    }

    public void setPassword(char[] password) {
        this.password = password;
    }

    public byte[] getCrcBuff() {
        return crcBuff;
    }

    public void setCrcBuff(byte[] crcBuff) {
        this.crcBuff = crcBuff;
    }

    public ArrayList getExtraDataRecords() {
        return extraDataRecords;
    }

    public void setExtraDataRecords(ArrayList extraDataRecords) {
        this.extraDataRecords = extraDataRecords;
    }

    public boolean isDataDescriptorExists() {
        return dataDescriptorExists;
    }

    public void setDataDescriptorExists(boolean dataDescriptorExists) {
        this.dataDescriptorExists = dataDescriptorExists;
    }

    public Zip64ExtendedInfo getZip64ExtendedInfo() {
        return zip64ExtendedInfo;
    }

    public void setZip64ExtendedInfo(Zip64ExtendedInfo zip64ExtendedInfo) {
        this.zip64ExtendedInfo = zip64ExtendedInfo;
    }

    public AESExtraDataRecord getAesExtraDataRecord() {
        return aesExtraDataRecord;
    }

    public void setAesExtraDataRecord(AESExtraDataRecord aesExtraDataRecord) {
        this.aesExtraDataRecord = aesExtraDataRecord;
    }

    public boolean isFileNameUTF8Encoded() {
        return fileNameUTF8Encoded;
    }

    public void setFileNameUTF8Encoded(boolean fileNameUTF8Encoded) {
        this.fileNameUTF8Encoded = fileNameUTF8Encoded;
    }


}
